/**
 * Vec.cpp
 * Coyright (c) 2009 Xiaofeng Gu. All Rights Reserved.
 * Author : Xiaofeng Gu
 *
 * Creation Data : 2009/06/11
 */

#include "stdafx.h"
#include "Vec.h"
#include <math.h>

#ifdef _DEBUG
#define new DEBUG_NEW
#endif

CVec::CVec()
: x(1.0), y(0), z(0)
{
}

CVec::CVec(double x1, double y1, double z1)
: x(x1), y(y1), z(z1)
{
}

CVec::~CVec()
{
}

double CVec::Length()
{
	return sqrt((*this) * (*this));
}

void CVec::RotateBy(const CVec& RefV, double Angle)
{
	CVec Axis = RefV;
	Axis.Identify();
	CVec AlongAxis = Axis * ((*this) * Axis);
	CVec AxisXInRotPlane = (*this) - AlongAxis;
	CVec AxisYInRotPlane = Axis ^/*Cross*/ AxisXInRotPlane;
	CVec InRotPlane = AxisXInRotPlane * cos(Angle) + AxisYInRotPlane * sin(Angle);
	(*this) = AlongAxis + InRotPlane;
}

double CVec::operator[](unsigned int i) const
{
	return *(&x + i);
}

double CVec::operator*(const CVec& Vec)
{
	return (*this)[0] * Vec[0] + (*this)[1] * Vec[1] + (*this)[2] * Vec[2];
}

inline CVec CVec::operator*(double K)
{
	CVec temp(
	x * K,
	y * K,
	z * K);

	return temp;
}

CVec& CVec::operator=(const CVec& Vec)
{
	x = Vec[0];
	y = Vec[1];
	z = Vec[2];
	return (*this);
}

CVec CVec::operator-(const CVec& Vec)
{
	CVec temp(
	x - Vec[0],
	y - Vec[1],
	z - Vec[2]);

	return temp;
}

CVec CVec::operator+(const CVec& Vec)
{
	CVec temp(
	x + Vec[0],
	y + Vec[1],
	z + Vec[2]);

	return temp;
}

CVec CVec::operator^(const CVec& Vec)
{
	CVec temp(
	y * Vec[2] - z * Vec[1],
	z * Vec[0] - x * Vec[2],
	x * Vec[1] - y * Vec[0]);

	return temp;
}

void CVec::Identify()
{
	double a = sqrt((*this) * (*this));
	x = x / a;
	y = y / a;
	z = z / a;
}

double CVec::CrossAngle(CVec& vec)
{
	return acos((*this) * vec / (sqrt((*this)*(*this)) * sqrt(vec*vec)));
}

void CVec::XVector()
{
	x = 1;
	y = 0;
	z = 0;
}

void CVec::YVector()
{
	x = 0;
	y = 1;
	z = 0;
}

void CVec::ZVector()
{
	x = 0;
	y = 0;
	z = 1;
}

void CVec::Zero()
{
	x = 0;
	y = 0;
	z = 0;
}

bool CVec::operator==(const CVec& Vec)
{
	CVec a = *this;
	a.Identify();
	CVec b = Vec;
	b.Identify();
	CVec c = a ^ b;
	if (fabs(c*c) < DELTA)
		return true;
	else
		return false;
}

void CVec::operator*=(double K)
{
	x = x * K;
	y = y * K;
	z = z * K;
}

bool CVec::Equal(double x1, double y1, double z1)
{
	if (fabs(x - x1) < DELTA &&
		fabs(y - y1) < DELTA &&
		fabs(z - z1) < DELTA)
		return true;
	else
		return false;
}